# -*- coding: utf-8 -*-
# !/usr/bin/env python3


"""
@Author   : Leonis.Li
@Email    : leonis.li.ext@zeiss.com
@Cellphone:
@Version  : 1.0
@License  : Apache Licence
@Script   : nacos_service.py
@CreateAt : 2023/10/17 17:59
@UpdateAt : 2023/10/17 17:59
Nacos -  Register
"""

import datetime
import json
import os
import requests
import socket
import threading
import time


# Beat check time interval(Seconds)
NACOS_BEAT_CHECK_INTERVAL = 5.0


# Set Nacos environment(Default: register NacosService in local environment)
REGISTER_ENV = os.environ.get("ENV")


# Nacos service parameters
NACOS_SERVICE_PARAMS = {
    "dev": {
        # Cloud
        "registerUrl": "http://nacos-cs.common:8848/nacos/v1/ns/instance",
        "beatCheckUrl": "http://nacos-cs.common:8848/nacos/v1/ns/instance/beat",
        "serviceName": "eva-service-ocr",
        "ip": None,
        "port": None,
        "namespaceId": "a510860e-48dc-4207-a0fa-16f14da21ae2",
        "username": "techplatform",
        "password": "mE;CeY&{2!"
    },
    "test": {
        # Cloud
        "registerUrl": "http://nacos-cs.common:8848/nacos/v1/ns/instance",
        "beatCheckUrl": "http://nacos-cs.common:8848/nacos/v1/ns/instance/beat",
        "serviceName": "eva-service-ocr",
        "ip": None,
        "port": None,
        "namespaceId": "8011bd51-e689-48e8-aabc-28d943ac8a78",
        "username": "",
        "password": " "
    },
    "default": {
        # Default  Use local env
        "registerUrl": "http://zdp.chinanorth3.cloudapp.chinacloudapi.cn:80/nacos/v1/ns/instance",
        "beatCheckUrl": "http://zdp.chinanorth3.cloudapp.chinacloudapi.cn:80/nacos/v1/ns/instance/beat",
        "serviceName": "eva-service-ocr",
        "ip": None,
        "port": None,
        "namespaceId": "98baba24-2fbe-45ea-a884-4673c3f7f671"
    },
    "local": {
        # Local test
        "registerUrl": "http://zdp.chinanorth3.cloudapp.chinacloudapi.cn:80/nacos/v1/ns/instance",
        "beatCheckUrl": "http://zdp.chinanorth3.cloudapp.chinacloudapi.cn:80/nacos/v1/ns/instance/beat",
        "serviceName": "eva-service-ocr",
        "ip": "10.15.33.87",
        "port": 5055,
        "namespaceId": "98baba24-2fbe-45ea-a884-4673c3f7f671"
    }
}


def get_nacos_env():

    # Set Env
    if not REGISTER_ENV:
        _env = 'local'
    else:
        _env = REGISTER_ENV.lower()

    return _env


def get_host_ip():
    """ Get host/docker internal ip."""

    st = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    try:
        st.connect(('10.255.255.255', 1))
        host_ip = st.getsockname()[0]
    except Exception:
        host_ip = '127.0.0.1'
    finally:
        st.close()

    return host_ip


def generate_service_params(register_env='default', register_service=False, beat_check_service=False):
    """Generate parameters: choose by register or beat-check service."""

    if (not register_service) and (not beat_check_service):
        raise ValueError("Parameter: both register_service and beat_check_service can't be True or False at same.")

    # Set nacos env
    if REGISTER_ENV:
        nacos_env = REGISTER_ENV.lower()
    else:
        nacos_env = register_env.lower()

    # Get parameters by nacos_env
    params = NACOS_SERVICE_PARAMS.get(nacos_env)

    # Get host ip from internal container
    if not params.get('ip'):
        # If not set in NACOS_SERVICE_PARAMS, get from os environment variables
        params['ip'] = get_host_ip()

    if not params.get('port'):
        # If not set in NACOS_SERVICE_PARAMS, get from os environment variables
        params['port'] = os.environ.get('port')

    if not params.get('serviceName'):
        # If not set in NACOS_SERVICE_PARAMS, get from os environment variables
        params['serviceName'] = os.environ.get('serviceName')

    if not params.get('namespaceId'):
        # If not set in NACOS_SERVICE_PARAMS, get from os environment variables
        params['namespaceId'] = os.environ.get('namespaceId')

    if not (params['ip'] and params['port']):
        # Check ip or port If both ip and port, miss configs
        raise ValueError('Parameters: ip or port not configured, please check.')

    # Api - host:ip details
    _api = "host: {}, port: {}".format(params['ip'], params['port'])

    if register_service:
        # register service
        _nacos_service_url = params.get("registerUrl")
    else:
        # beat check service
        _nacos_service_url = params.get("beatCheckUrl")

    # Post params
    _nacos_service_params = {
        "ip": params.get("ip"),
        "port": params.get("port"),
        "serviceName": params.get("serviceName"),
        "username": params.get("username"),
        "password": params.get("password"),
        "namespaceId": params.get("namespaceId")
    }

    return _nacos_service_url, _nacos_service_params, _api


def register_nacos(register_env='default'):
    """ Register service to nacos center. """

    # Get register service and api details(host, port)
    register_url, register_params, api_info = generate_service_params(register_env=register_env, register_service=True)

    # Register service
    register_time = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
    response = requests.post(register_url, data=register_params)

    print(f"[{register_time}] Register api({api_info}) to nacos center, status code：{response.status_code}")


def beat_check_nacos(register_env='default'):

    # Get register service and api details(host, port)
    beat_check_url, beat_params, api_info = generate_service_params(register_env=register_env, beat_check_service=True)

    while True:

        # Beat check process
        check_at = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
        check_response = requests.put(beat_check_url, data=beat_params)
        print(f"[{check_at}] Nacos beat check api({api_info}) service, status code：{check_response.status_code}")

        # Time sleep
        time.sleep(NACOS_BEAT_CHECK_INTERVAL)


if __name__ == "__main__":

    # Get nacos env
    env = get_nacos_env()

    # Register container api to NacosCenter
    register_nacos(register_env=env)

    # Beat check service
    threading.Timer(NACOS_BEAT_CHECK_INTERVAL, beat_check_nacos(register_env=env)).start()
